/**
 * @(#)Ship.java
 *
 *
 * @author 
 * @version 1.00 2009/12/7
 */
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.util.ArrayList;

public class Ship //extends Path2D.Float
{
	private static final int NUM_LINES = 4;
	public static final double PI = 3.1415926535897932384626433832;
	private static final double SIZE = 45;
	private double heading;
	private double omega;
	private double xVelocity;
	private double yVelocity;
	private double velocity;
	private double xPosition;
	private double yPosition;
	private GeneralPath shipShape;
	private AffineTransform changeInShip;
	private static final boolean INVINCIBLE = false;
	private static final int BURST_SHOT_SIZE = 30;
	private static final int SHOT_SPEED = 10;
	private static final double RECOIL = 0.0;
	
    public Ship() 
    {
    	//this = new Path2D();
    	heading = 0;
    	velocity = 0;
    	xVelocity = 0;
    	yVelocity = 0;
    	omega = 0;
    	xPosition = AsteroidsFrame.FRAME_WIDTH/2;
    	yPosition = AsteroidsFrame.FRAME_HEIGHT/2;
		updateShip();
    	//changeInShip = new AffineTransform();
    }
    
    public void updateShip()
    {
    	changeInShip = new AffineTransform();
    	//changeInShip.translate(xVelocity, yVelocity);
    	heading+= omega;
    	heading = heading % (2*PI);	
    	//double xVelocity = velocity * Math.sin(heading);
    	//double yVelocity = velocity * Math.cos(heading);
    	xPosition-=xVelocity;
    	
    	//Wrap the ship around
    	if(xPosition < 0)
    	{
    		xPosition += AsteroidsFrame.FRAME_WIDTH;
    	}
    	else if(xPosition > AsteroidsFrame.FRAME_WIDTH)
    	{
    		xPosition -= AsteroidsFrame.FRAME_WIDTH;
    	}
    	
    	if(yPosition < 0)
    	{
    		yPosition += AsteroidsFrame.FRAME_HEIGHT;
    	}
    	else if(yPosition > AsteroidsFrame.FRAME_HEIGHT)
    	{
    		yPosition -= AsteroidsFrame.FRAME_HEIGHT;
    	}
    	
    	yPosition-=yVelocity;
    	
    	changeInShip.rotate(heading, xPosition, yPosition + 20);
    	shipShape = new GeneralPath(GeneralPath.WIND_EVEN_ODD, NUM_LINES);
    	shipShape.moveTo(xPosition, yPosition  );
    	shipShape.lineTo(xPosition + SIZE*Math.sin(PI/8), yPosition + SIZE*Math.cos(-PI/8));
    	shipShape.lineTo(xPosition, yPosition + 25);
    	shipShape.lineTo(xPosition - SIZE*Math.sin(PI/8), yPosition + SIZE*Math.cos(-PI/8));
    	shipShape.closePath();
    	shipShape.transform(changeInShip);
    }
	public GeneralPath getShipShape()
	{
		return shipShape;
	}
    
    public void printSchematics()
    {
    	System.out.println("velocities = " + xVelocity + ", " + yVelocity + "positions = " + xPosition + "," + yPosition + " heading = " + heading);
    }
    
    public void Accelerate(double acceleration, double alpha)
    {
    	//velocity += acceleration;
    	xVelocity -= acceleration*Math.sin(heading);
    	yVelocity += acceleration*Math.cos(heading);
    	heading+= alpha;
    }
    
    public void FullBrake()
    {
    	xVelocity = 0;
    	yVelocity = 0;
    }
    
    public void FullForward()
    {
    	double fullVelocity = Math.sqrt(Math.pow(xVelocity,2) + Math.pow(yVelocity,2));
    	xVelocity=-fullVelocity*Math.sin(heading);
    	yVelocity=fullVelocity*Math.cos(heading);
    }
    
    public void FullReverse()
    {
    	double fullVelocity = Math.sqrt(Math.pow(xVelocity,2) + Math.pow(yVelocity,2));
    	xVelocity=fullVelocity*Math.sin(heading);
    	yVelocity=-fullVelocity*Math.cos(heading);
    }
    public Shot FireShot()
    {
    	Accelerate(RECOIL, 0);
    	return new Shot(heading, shipShape.getCurrentPoint().getX(), shipShape.getCurrentPoint().getY(), getFullVelocity() + SHOT_SPEED);	
    }
    public SuperShot FireSuperShot(SuperShot.SuperType... type)
    {
    	Accelerate(RECOIL, 0);
    	return new SuperShot(heading, shipShape.getCurrentPoint().getX(), shipShape.getCurrentPoint().getY(), getFullVelocity() + SHOT_SPEED, type);
    }
    public SuperShot[] FireSuperBurst(SuperShot.SuperType... type)
    {
    	Accelerate(RECOIL * 5 , 0);
    	SuperShot[] return_shots = new SuperShot[BURST_SHOT_SIZE];
    	for(int i = 0; i < BURST_SHOT_SIZE; i++)
    	{
    		return_shots[i] = new SuperShot(heading + 2*PI*i/BURST_SHOT_SIZE, shipShape.getCurrentPoint().getX(), shipShape.getCurrentPoint().getY(), getFullVelocity() + SHOT_SPEED, type);
    	}
    	return return_shots;
    }
     public void FireSuperBurst(ArrayList<SuperShot> shot_list, SuperShot.SuperType... type)
    {
    	Accelerate(RECOIL * 5, 0);
    	//SuperShot[] return_shots = new SuperShot[BURST_SHOT_SIZE];
    	for(int i = 0; i < BURST_SHOT_SIZE; i++)
    	{
    		shot_list.add(new SuperShot(heading + 2*PI*i/BURST_SHOT_SIZE, shipShape.getCurrentPoint().getX(), shipShape.getCurrentPoint().getY(), getFullVelocity() + SHOT_SPEED, type));
    	}
    	//return return_shots;
    }
    public double getFullVelocity()
    {
    	return Math.sqrt(Math.pow(xVelocity,2) + Math.pow(yVelocity,2));
    }
    
    public boolean isHit(Rock[] rocks)
    {
    	for(int i = 0; i < rocks.length; i++)
    	{
    		if(shipShape.intersects(rocks[i].getRockShape().getBounds2D()))
    		{
    			return true;
    		}
    	}
    	
    	return false;
    }
    
    public Point2D.Double GetPosition()
    {
    	return new Point2D.Double(xPosition, yPosition);
    }
    
    public boolean IsInvincible()
    {
    	return INVINCIBLE;
    }
}